package com.sunagy.demand.front.controller.api;

import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.OSSObject;
import com.sunagy.demand.front.VO.ResultVO;
import com.sunagy.demand.front.exception.FileException;
import com.sunagy.demand.front.thirdparty.Base64Image;
import com.sunagy.demand.front.thirdparty.aliyun.AliOssClient;
import com.sunagy.demand.front.thirdparty.wechat.WechatTokenHelper;
import com.sunagy.demand.front.utils.FileUtil;
import com.sunagy.demand.front.utils.ResultVOUtil;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * desc：#TODO fill me ！
 * author：三餘無夢生
 * date：2018/4/27
 * time：下午5:24
 */
@Slf4j
@RestController
@RequestMapping("")
@Api(value = "通用阿里云OSS", description = "阿里云oss相关接口")
public class AliOssApi extends BaseFileApi {

    @Autowired
    private AliOssClient aliOssClient;

    @Autowired
    private WechatTokenHelper wechatTokenHelper;

    public AliOssApi(){
        log.info("AliOssApi init");
    }

    /**
     * 上传文件到阿里云OSS
     *
     * @param file
     * @param request
     * @return
     */
    @RequestMapping(value = "oss/image", method = RequestMethod.POST)
    @ResponseBody
    public ResultVO uploadToAliOss(HttpServletRequest request,
                                   @RequestParam(value = "file") MultipartFile file
    ) {
        String path = request.getParameter("path");
        if(path == null){
            path = "image" + File.separator + new SimpleDateFormat("yyMM").format(new Date());
        }
        String originalFilename = file.getOriginalFilename();
        String saveName = FileUtil.generateName(originalFilename);
        String key = path + File.separator +saveName;

        try {
            aliOssClient.putObject(key, file.getInputStream(), file.getSize());

            String realUrl = aliOssClient.getUrl(key);

            Map<String, Object> data = new HashMap<>();
            data.put("mime", file.getContentType());
            data.put("size", file.getSize());
            data.put("name", file.getOriginalFilename());
            data.put("saveName", saveName);
            data.put("saveUrl", realUrl);
            data.put("path", URLEncoder.encode(key, "UTF-8"));
            return ResultVOUtil.success(data);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            return ResultVOUtil.fail("上传异常");
        }
    }

    /**
     * 上传文件
     *
     * @param image
     * @return
     */
    @RequestMapping(value = "oss/image/base64", method = RequestMethod.POST)
    @ResponseBody
    public ResultVO uploadBase64(@RequestBody Base64Image image) {
        if(image == null || image.getData() == null){
            return ResultVOUtil.fail("参数错误");
        }
        String path = image.getPath();
        if(path == null){
            path = "image" + File.separator + new SimpleDateFormat("yyMM").format(new Date());
        }
        if(image.getSuffix() == null){
            image.setSuffix(image.getData().substring(11, image.getData().indexOf(";")));
        }
        String saveName = UUID.randomUUID().toString().replace("-", "") + "." + image.getSuffix();

        String key = path + File.separator +saveName;
        try{
            String imageData = image.getData().substring(image.getData().indexOf(",")+1);
            byte[] result = Base64.getDecoder().decode(imageData.getBytes());
            aliOssClient.putObject(key, new ByteArrayInputStream(result), result.length);

            String realUrl = aliOssClient.getUrl(key);
            Map<String, Object> data = new HashMap<>();
            data.put("mime", "image/"+image.getSuffix());
            data.put("size", result.length);
            data.put("name", saveName);
            data.put("saveName", saveName);
            data.put("saveUrl", realUrl);
            data.put("path", key);
            return ResultVOUtil.success(data);
        }catch (Exception e){
            log.error(e.getMessage(), e);
            throw new FileException(-1, e.getMessage());
        }

    }

    @RequestMapping(value = "oss/image/{type}/{path}/{time}/{key:.+}", method = RequestMethod.GET)
    public ResponseEntity<?> getFileFromAliOss(
            @PathVariable("type") String type,
            @PathVariable("path") String path,
            @PathVariable("time") String time,
            @PathVariable String key) {
        try {
            key = "image" + File.separator + type + File.separator + path + File.separator + time + File.separator + key;
            OSSObject object = aliOssClient.getObject(URLEncoder.encode(key, "UTF-8"));
            String fileName = key.substring(key.lastIndexOf(File.separator) + 1);
            HttpHeaders headers=new HttpHeaders();
            headers.add("Content-Type", object.getObjectMetadata().getContentType());
            headers.add("content-disposition", "attachment;filename=" + fileName);
            headers.add("Content-Length", object.getObjectMetadata().getContentLength() + "");

            byte[] body = new byte[object.getObjectContent().available()];
            int i = object.getObjectContent().read(body);
            return new ResponseEntity<>(body, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.notFound().build();
        }
    }

    @RequestMapping(value = "oss/image/{path}/{time}/{key:.+}", method = RequestMethod.GET)
    public ResponseEntity<?> getFileFromAliOss(
            @PathVariable("path") String path,
            @PathVariable("time") String time,
            @PathVariable String key) {
        try {
            key = "image" + File.separator + path + File.separator + time + File.separator + key;
            OSSObject object = aliOssClient.getObject(URLEncoder.encode(key, "UTF-8"));
            String fileName = key.substring(key.lastIndexOf(File.separator) + 1);
            HttpHeaders headers=new HttpHeaders();
            headers.add("Content-Type", object.getObjectMetadata().getContentType());
            headers.add("content-disposition", "attachment;filename=" + fileName);
            headers.add("Content-Length", object.getObjectMetadata().getContentLength() + "");

            byte[] body = new byte[object.getObjectContent().available()];
            int i = object.getObjectContent().read(body);
            return new ResponseEntity<>(body, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.notFound().build();
        }
    }

    @RequestMapping(value = "oss/image/{time}/{key:.+}", method = RequestMethod.GET)
    public ResponseEntity<?> getFileFromAliOss(
            @PathVariable("time") String time,
            @PathVariable String key) {
        try {
            key = "image" + File.separator + time + File.separator + key;
            OSSObject object = aliOssClient.getObject(URLEncoder.encode(key, "UTF-8"));
            String fileName = key.substring(key.lastIndexOf(File.separator) + 1);
            HttpHeaders headers=new HttpHeaders();
            headers.add("Content-Type", object.getObjectMetadata().getContentType());
            headers.add("content-disposition", "attachment;filename=" + fileName);
            headers.add("Content-Length", object.getObjectMetadata().getContentLength() + "");

            byte[] body = new byte[object.getObjectContent().available()];
            int i = object.getObjectContent().read(body);
            return new ResponseEntity<>(body, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.notFound().build();
        }
    }

    @RequestMapping(value = "oss/image/{key:.+}", method = RequestMethod.GET)
    public ResponseEntity<?> getFileFromAliOss(@PathVariable String key) {
        try {
            OSSObject object = aliOssClient.getObject(key);
            String fileName = key.substring(key.lastIndexOf(File.separator) + 1);
            HttpHeaders headers=new HttpHeaders();
            headers.add("Content-Type", object.getObjectMetadata().getContentType());
            headers.add("content-disposition", "attachment;filename=" + fileName);
            headers.add("Content-Length", object.getObjectMetadata().getContentLength() + "");

            byte[] body = new byte[object.getObjectContent().available()];
            int i = object.getObjectContent().read(body);
            return new ResponseEntity<>(body, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 文件删除，从阿里云删除文件
     * @param key
     * @return
     */
    @RequestMapping(value = "oss/image/{key:.+}", method = { RequestMethod.DELETE })
    @ResponseBody
    public ResultVO deleteImageFromAliOss(@PathVariable String key) {
        try {
            aliOssClient.deleteObject(key);
            return ResultVOUtil.success(key);
        } catch (OSSException e) {
            log.error(e.getMessage(), e);
            return ResultVOUtil.fail("删除异常");
        }
    }

    /**
     * 文件删除，从阿里云删除文件
     * @param key
     * @return
     */
    @RequestMapping(value = "oss/{key:.+}", method = { RequestMethod.DELETE })
    @ResponseBody
    public ResultVO deleteImage(@PathVariable String key) {
        try {
            aliOssClient.deleteObject(key);
            return ResultVOUtil.success(key);
        } catch (OSSException e) {
            log.error(e.getMessage(), e);
            return ResultVOUtil.fail("删除异常");
        }
    }



    /**
     * 上传文件到阿里云OSS
     *
     * @param file
     * @param request
     * @return
     */
    @ApiOperation(value = "上传文件到阿里云OSS", notes = "上传文件到阿里云OSS(spring cloud 2.0MultipartFile会报错)")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType="file",name = "file", value = "file", required = false, paramType = "form"),
    })
    @ApiResponses({
            @ApiResponse(code = 500, message = "接口异常")
    })
    @RequestMapping(value = "oss/file", method = RequestMethod.POST)
    public ResultVO uploadFile(HttpServletRequest request,
                                 @RequestParam(value = "file") MultipartFile file
    ) {
        String path = request.getParameter("path");
        if(path == null){
            path = "file" + File.separator + new SimpleDateFormat("yyMM").format(new Date());
        }
        String originalFilename = file.getOriginalFilename();
        String saveName = FileUtil.generateName(originalFilename);
        String key = path + File.separator +saveName;

        try {
            aliOssClient.putObject(key, file.getInputStream(), file.getSize());

            String realUrl = aliOssClient.getUrl(key);

            Map<String, Object> data = new HashMap<>();
            data.put("mime", file.getContentType());
            data.put("size", file.getSize());
            data.put("name", file.getOriginalFilename());
            data.put("saveName", saveName);
            data.put("saveUrl", realUrl);
            data.put("path", URLEncoder.encode(key, "UTF-8"));
            return ResultVOUtil.success(data);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            return ResultVOUtil.fail("上传异常");
        }
    }

    @RequestMapping(value = "oss/file/{type}/{path}/{time}/{key:.+}", method = RequestMethod.GET)
    public ResponseEntity<?> getFile(
            @PathVariable("type") String type,
            @PathVariable("path") String path,
            @PathVariable("time") String time,
            @PathVariable String key) {
        try {
            key = "file" + File.separator + type + File.separator + path + File.separator + time + File.separator + key;
            OSSObject object = aliOssClient.getObject(URLEncoder.encode(key, "UTF-8"));
            String fileName = key.substring(key.lastIndexOf(File.separator) + 1);
            HttpHeaders headers=new HttpHeaders();
            headers.add("Content-Type", object.getObjectMetadata().getContentType());
            headers.add("content-disposition", "attachment;filename=" + fileName);
            headers.add("Content-Length", object.getObjectMetadata().getContentLength() + "");

            byte[] body = new byte[object.getObjectContent().available()];
            int i = object.getObjectContent().read(body);
            return new ResponseEntity<>(body, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.notFound().build();
        }
    }

    @RequestMapping(value = "oss/file/{path}/{time}/{key:.+}", method = RequestMethod.GET)
    public ResponseEntity<?> getFile(
            @PathVariable("path") String path,
            @PathVariable("time") String time,
            @PathVariable String key) {
        try {
            key = "file" + File.separator + path + File.separator + time + File.separator + key;
            OSSObject object = aliOssClient.getObject(URLEncoder.encode(key, "UTF-8"));
            String fileName = key.substring(key.lastIndexOf(File.separator) + 1);
            HttpHeaders headers=new HttpHeaders();
            headers.add("Content-Type", object.getObjectMetadata().getContentType());
            headers.add("content-disposition", "attachment;filename=" + fileName);
            headers.add("Content-Length", object.getObjectMetadata().getContentLength() + "");

            byte[] body = new byte[object.getObjectContent().available()];
            int i = object.getObjectContent().read(body);
            return new ResponseEntity<>(body, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.notFound().build();
        }
    }

    @RequestMapping(value = "oss/file/{time}/{key:.+}", method = RequestMethod.GET)
    public ResponseEntity<?> getFile(
            @PathVariable("time") String time,
            @PathVariable String key) {
        try {
            key = "file" + File.separator + time + File.separator + key;
            OSSObject object = aliOssClient.getObject(URLEncoder.encode(key, "UTF-8"));
            String fileName = key.substring(key.lastIndexOf(File.separator) + 1);
            HttpHeaders headers=new HttpHeaders();
            headers.add("Content-Type", object.getObjectMetadata().getContentType());
            headers.add("content-disposition", "attachment;filename=" + fileName);
            headers.add("Content-Length", object.getObjectMetadata().getContentLength() + "");

            byte[] body = new byte[object.getObjectContent().available()];
            int i = object.getObjectContent().read(body);
            return new ResponseEntity<>(body, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.notFound().build();
        }
    }

    @RequestMapping(value = "oss/file/{key:.+}", method = RequestMethod.GET)
    public ResponseEntity<?> getFile(@PathVariable String key) {
        try {
            OSSObject object = aliOssClient.getObject(key);
            String fileName = key.substring(key.lastIndexOf(File.separator) + 1);
            HttpHeaders headers=new HttpHeaders();
            headers.add("Content-Type", object.getObjectMetadata().getContentType());
            headers.add("content-disposition", "attachment;filename=" + fileName);
            headers.add("Content-Length", object.getObjectMetadata().getContentLength() + "");

            byte[] body = new byte[object.getObjectContent().available()];
            int i = object.getObjectContent().read(body);
            return new ResponseEntity<>(body, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 文件删除，从阿里云删除文件
     * @param key
     * @return
     */
    @RequestMapping(value = "oss/file/{key:.+}", method = { RequestMethod.DELETE })
    @ResponseBody
    public ResultVO deleteFile(@PathVariable String key) {
        try {
            aliOssClient.deleteObject(key);
            return ResultVOUtil.success(key);
        } catch (OSSException e) {
            log.error(e.getMessage(), e);
            return ResultVOUtil.fail("删除异常");
        }
    }

    /**
     * 上传文件到阿里云存储
     *
     * @param mediaId
     * @return
     */
    @RequestMapping(value = "/oss/image/wechat/{mediaId}", method = RequestMethod.POST)
    @ResponseBody
    public ResultVO uploadWechatMediaToQniu(@PathVariable(value = "mediaId") String mediaId
    ) {
        String weiXinToken = wechatTokenHelper.accessToken();
        String _url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token="
                + weiXinToken + "&media_id=" + mediaId;

        String key = "image" + File.separator + "wechat" + File.separator + mediaId;
        File f = new File(FileUtils.getTempDirectoryPath() + File.separator + key);
        try{
            URL url = new URL(_url);
            FileUtils.copyURLToFile(url, f);
            aliOssClient.putObject(key, f.getPath());
            String realUrl = aliOssClient.getUrl(key);

            Map<String, Object> data = new HashMap<>();
            data.put("size", f.length());
            data.put("name", f.getName());
            data.put("saveName", mediaId);
            data.put("saveUrl", realUrl);
            data.put("path", URLEncoder.encode(key, "UTF-8"));
            return ResultVOUtil.success(data);
        }catch (IOException e){
            log.error(e.getMessage(), e);
        }
        return ResultVOUtil.fail("上传异常");
    }
}
